use crate::config::Config;
use crate::errors::{BinanceError, Result};
use crate::ws::user_types::{AccountUpdateRaw, MarginCallRaw, OrderUpdateRaw, UserStreamEvent};
use crate::ws::ws_client::WsClient;
use serde_json::Value;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};

/// 用户数据流订阅：接收 listenKey 下的事件流，转换为 UserStreamEvent 枚举
pub async fn subscribe_user_stream(
    listen_key: &str,
    config: &Config,
) -> Result<UnboundedReceiver<UserStreamEvent>> {
    let url = format!("{}/ws/{}", config.ws_base_url(), listen_key);
    let (client, mut raw_rx) = WsClient::new(&url, config.proxy.clone())
        .await
        .map_err(|e| BinanceError::Other(format!("WebSocket connect failed: {}", e)))?;

    let (tx, rx) = unbounded_channel();

    tokio::spawn(async move {
        while let Some(raw_msg) = raw_rx.recv().await {
            let Ok(json) = serde_json::from_value::<Value>(raw_msg) else {
                continue;
            };

            match json.get("e").and_then(|v| v.as_str()) {
                Some("ACCOUNT_UPDATE") => {
                    if let Ok(raw) = serde_json::from_value::<AccountUpdateRaw>(json.clone()) {
                        if let Some(event) = raw.to_model() {
                            let _ = tx.send(UserStreamEvent::AccountUpdate(event));
                        }
                    }
                }
                Some("ORDER_TRADE_UPDATE") => {
                    if let Ok(raw) = serde_json::from_value::<OrderUpdateRaw>(json.clone()) {
                        if let Some(event) = raw.to_model() {
                            let _ = tx.send(UserStreamEvent::OrderUpdate(event));
                        }
                    }
                }
                Some("MARGIN_CALL") => {
                    if let Ok(raw) = serde_json::from_value::<MarginCallRaw>(json.clone()) {
                        if let Some(event) = raw.to_model() {
                            let _ = tx.send(UserStreamEvent::MarginCall(event));
                        }
                    }
                }
                Some(other) => {
                    tracing::warn!(target: "binance_ws", "Unhandled user event: {}", other);
                }
                None => {
                    tracing::warn!(target: "binance_ws", "Unknown event payload: {:?}", json);
                }
            }
        }

        drop(client); // 明确释放连接句柄
    });

    Ok(rx)
}
